package com.tcm.controller.backend;

import cn.hutool.extra.pinyin.PinyinUtil;
import com.tcm.common.enums.ResponseEnum;
import com.tcm.entity.SocialClazz;
import com.tcm.entity.SocialProject;
import com.tcm.entity.bo.SocialStudentExcel;
import com.tcm.entity.dto.SocialClazzUpdateDto;
import com.tcm.entity.dto.SocialProjectUpdateDto;
import com.tcm.entity.dto.SocialStudentUpdateDto;
import com.tcm.entity.dto.param.*;
import com.tcm.entity.resp.PageR;
import com.tcm.entity.resp.R;
import com.tcm.entity.vo.BatchImportResult;
import com.tcm.entity.vo.SocialStudentListResult;
import com.tcm.exception.EntityAlreadyExistException;
import com.tcm.exception.EntityInvalidException;
import com.tcm.service.SocialClazzService;
import com.tcm.service.SocialProjectService;
import com.tcm.service.SocialStudentService;
import com.tcm.utils.AccessTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Guqier
 * @version 1.0
 * @date 2023/7/26 16:10
 */
@Slf4j
@RestController
@RequestMapping("/pc/social")
public class SocialController {

    @Autowired
    private SocialProjectService socialProjectService;

    @Autowired
    private SocialClazzService socialClazzService;

    @Autowired
    private SocialStudentService socialStudentService;

    /**
     * 添加社会化项目
     * @param dto 社会化项目信息数据封装参数
     * @param request http请求对象
     * @return 处理结果
     */
    @RequestMapping(value = "/project", method = RequestMethod.POST)
    public R addSocialProject(@RequestBody @Valid SocialProjectUpdateDto dto, HttpServletRequest request){
        boolean b = false;
        try {
            b = socialProjectService.addSocialProject(dto, AccessTokenUtil.getUserId(request));
        } catch (EntityAlreadyExistException e) {
            return R.fail(0, e.getMessage());
        }
        return b ? R.success() : R.fail(ResponseEnum.DATABASE_OPERATION_FAIL);
    }

    /**
     * 删除社会化项目
     * @param ids 社会化项目ID列表
     * @param request http请求对象
     * @return 响应结果
     */
    @RequestMapping(value = "/project", method = RequestMethod.DELETE)
    public R removeSocialProject(@RequestParam("ids") List<Long> ids, HttpServletRequest request){
        if (CollectionUtils.isEmpty(ids)) {
            return R.fail(ResponseEnum.PARAM_IS_BLANK);
        }
        boolean b = false;
        try {
            b = socialProjectService.removeSocialProject(ids, AccessTokenUtil.getUserId(request));
        } catch (Exception e) {
            return R.fail(0, e.getMessage());
        }
        return b ? R.success() : R.fail(ResponseEnum.PARAM_IS_INVAlID);
    }

    /**
     * 修改社会化项目信息
     * @param dto 社会化项目信息数据封装参数
     * @param request http请求对象
     * @return 处理结果
     */
    @RequestMapping(value = "/project", method = RequestMethod.PUT)
    public R modifySocialProject(@RequestBody @Valid SocialProjectUpdateDto dto, HttpServletRequest request){
        if (dto.getId() == null) {
            return R.fail(ResponseEnum.PARAM_IS_BLANK);
        }

        return socialProjectService.modifySocialProject(dto, AccessTokenUtil.getUserId(request)) ? R.success() : R.fail(ResponseEnum.DATABASE_OPERATION_FAIL);
    }

    /**
     * 分页获取社会化项目列表
     * @param param 分页参数
     * @return 社会化项目列表
     */
    @RequestMapping(value = "/project", method = RequestMethod.GET)
    public R getSocialProjectListByPage(SocialProjectPageParam param){
        PageR<SocialProjectUpdateDto> socialProjectList = socialProjectService.getSocialProjectListByPage(param);
        return R.success(socialProjectList);
    }

    /**
     * 根据ID查询社会化项目信息
     * @param id 社会化项目ID
     * @return 社会化项目信息
     */
    @RequestMapping(value = "/project/info", method = RequestMethod.GET)
    public R getSocialProjectById(@RequestParam Long id){
        SocialProject project = socialProjectService.getById(id);
        if (project == null){
            return R.fail(ResponseEnum.PARAM_IS_INVAlID);
        }else {
            SocialProjectUpdateDto dto = new SocialProjectUpdateDto();
            BeanUtils.copyProperties(project, dto);
            return R.success(dto);
        }
    }

    /**
     * 获取社会化项目选择框列表
     * @return 社会化项目选择框列表
     */
    @RequestMapping(value = "/project/all", method = RequestMethod.GET)
    public R getSocialProjectListAll(){
        return R.success(socialProjectService.list().stream().map(socialProject -> {
            SocialProjectUpdateDto dto = new SocialProjectUpdateDto();
            BeanUtils.copyProperties(socialProject, dto);
            return dto;
        }).collect(Collectors.toList()));
    }

    /**
     * 添加社会化班级
     * @param dto 社会化班级数据更新封装类
     * @param request http请求对象
     * @return 处理结果，true为成功
     */
    @RequestMapping(value = "/clazz", method = RequestMethod.POST)
    public R addSocialClazz(@RequestBody @Valid SocialClazzUpdateDto dto, HttpServletRequest request){
        boolean b = false;
        try {
            b = socialClazzService.addSocialClazz(dto, AccessTokenUtil.getUserId(request));
        } catch (EntityInvalidException e) {
            return R.fail(0, e.getMessage());
        }
        return b ? R.success() : R.fail(ResponseEnum.DATABASE_OPERATION_FAIL);
    }

    /**
     * 修改社会化班级信息
     * @param dto 社会化班级数据更新封装类
     * @param request http对象
     * @return 处理结果
     */
    @RequestMapping(value = "/clazz", method = RequestMethod.PUT)
    public R modifySocialClazz(@RequestBody @Valid SocialClazzUpdateDto dto, HttpServletRequest request){
        if (dto.getId() == null) {
            return R.fail(ResponseEnum.PARAM_IS_BLANK);
        }
        boolean b = false;
        try {
            b = socialClazzService.modifySocialClazz(dto, AccessTokenUtil.getUserId(request));
        } catch (EntityInvalidException e) {
            return R.fail(0, e.getMessage());
        }
        return b ? R.success() : R.fail(ResponseEnum.DATABASE_OPERATION_FAIL);
    }

    /**
     * 批量删除社会化班级
     * @param ids 社会化班级列表
     * @param request http请求对象
     * @return 处理结果
     */
    @RequestMapping(value = "/clazz", method = RequestMethod.DELETE)
    public R removeSocialClazz(@RequestParam("ids") List<Long> ids, HttpServletRequest request){
        boolean b = false;
        try {
            b = socialClazzService.removeSocialClazz(ids, AccessTokenUtil.getUserId(request));
        } catch (Exception e) {
            return R.fail(0, e.getMessage());
        }
        return b ? R.success() : R.fail(ResponseEnum.PARAM_IS_INVAlID);
    }

    /**
     * 分页获取社会化班级列表
     * @param param 分页参数封装
     * @return 社会化班级列表
     */
    @RequestMapping(value = "/clazz", method = RequestMethod.GET)
    public R getSocialClazzListByPage(SocialClazzPageParam param){
        PageR<SocialClazzUpdateDto> socialClazzListByPage = socialClazzService.getSocialClazzListByPage(param);
        return R.success(socialClazzListByPage);
    }

    /**
     * 通过社会化项目ID获取社会化班级列表
     * @param projectId 社会化项目ID
     * @return 社会化班级列表
     */
    @RequestMapping(value = "/clazz/proj", method = RequestMethod.GET)
    public R getSocialClazzListByProjectId(@RequestParam Long projectId){
        List<SocialClazzUpdateDto> list = socialClazzService.getSocialClazzListByProjectId(projectId);
        return R.success(list);
    }

    /**
     * 设置社会化班级授课教师
     * @param param 参数封装
     * @param request 请求对象
     * @return 处理结果，true为成功
     */
    @RequestMapping(value = "/clazz/teacher", method = RequestMethod.POST)
    public R setSocialClazzTeacher(@RequestBody @Valid SocialClazzSetTeacherParam param, HttpServletRequest request){
        if (CollectionUtils.isEmpty(param.getTeacherIds())) {
            return R.fail(ResponseEnum.PARAM_IS_BLANK);
        }
        return socialClazzService.setSocialClazzTeacher(param, AccessTokenUtil.getUserId(request)) ? R.success() : R.fail(ResponseEnum.PARAM_IS_INVAlID);
    }

    /**
     * 根据当前登录教师获得社会化班级列表
     * @param request 请求对象
     * @return 社会化班级列表
     */
    @RequestMapping(value = "/clazz/teacher", method = RequestMethod.GET)
    public R getSocialClazzListAccordingToTeacher(HttpServletRequest request){
        List<SocialClazzUpdateDto> socialClazzList = socialClazzService.getSocialClazzListAccordingToTeacher(AccessTokenUtil.getUserId(request));
        if (socialClazzList == null) {
            return R.fail(0, "当前登录非教师用户");
        }
        return R.success(socialClazzList);
    }


    /**
     * 添加社会化学员
     * @param dto 社会化学员数据更新封装类
     * @param request http请求对象
     * @return 处理结果
     */
    @RequestMapping(value = "/student", method = RequestMethod.POST)
    public R addSocialStudent(@RequestBody @Valid SocialStudentUpdateDto dto, HttpServletRequest request){
        boolean b = false;
        try {
            b = socialStudentService.addSocialStudent(dto, AccessTokenUtil.getUserId(request));
        } catch (Exception e) {
            return R.fail(0, e.getMessage());
        }
        return b ? R.success() : R.fail(ResponseEnum.PARAM_IS_INVAlID);
    }

    /**
     * 修改社会化学员
     * @param param 尝试封装
     * @param request http请求对象
     * @return 处理结果
     */
    @RequestMapping(value = "/student", method = RequestMethod.PUT)
    public R modifySocialStudent(@RequestBody @Valid SocialStudentUpdateParam param, HttpServletRequest request){
        if (param.getId() == null) {
            return R.fail(ResponseEnum.PARAM_IS_BLANK);
        }
        boolean b = false;
        try {
            b = socialStudentService.modifySocialStudent(param, AccessTokenUtil.getUserId(request));
        } catch (Exception e) {
            return R.fail(0, e.getMessage());
        }
        return b ? R.success() : R.fail(ResponseEnum.PARAM_IS_INVAlID);
    }

    /**
     * 删除社会化学员
     * @param ids 社会化学员ID列表
     * @param request http请求对象
     * @return 处理结果
     */
    @RequestMapping(value = "/student", method = RequestMethod.DELETE)
    public R removeSocialStudent(@RequestParam("ids") List<Long> ids, HttpServletRequest request){
        if (CollectionUtils.isEmpty(ids)) {
            return R.fail(ResponseEnum.PARAM_IS_BLANK);
        }
        boolean b = false;
        try {
            b = socialStudentService.removeSocialStudent(ids, AccessTokenUtil.getUserId(request));
        } catch (Exception e) {
            return R.fail(0, e.getMessage());
        }
        return b ? R.success() : R.fail(ResponseEnum.PARAM_IS_INVAlID);
    }

    /**
     * 分页获取社会化学员列表
     * @param param 分页参数
     * @return 社会化学员列表
     */
    @RequestMapping(value = "/student", method = RequestMethod.GET)
    public R getSocialStudentListByPage(SocialStudentPageParam param){
        if (param.getPage() == null || param.getPageSize() == null) {
            return R.fail(ResponseEnum.PARAM_IS_BLANK);
        }
        PageR<SocialStudentListResult> socialStudentListByPage = socialStudentService.getSocialStudentListByPage(param);
        return R.success(socialStudentListByPage);
    }

    /**
     * 批量导入社会化信息信息校验
     * @param file excel文件
     * @return 上传结果
     */
    @RequestMapping(value = "/student/import", method = RequestMethod.POST)
    public R batchImportSocialStudentInfo(MultipartFile file){
        if (file == null) {
            return R.fail(ResponseEnum.PARAM_IS_BLANK);
        }
        BatchImportResult<SocialStudentExcel> result = null;
        try {
            result = socialStudentService.importSocialStudentInfo(file);
        } catch (IOException e) {
            return R.fail(0, e.getMessage());
        }
        return R.success(result);
    }

    /**
     * 确认导入社会化学员信息
     * @param uuid 导入uuid
     * @return 响应结果
     */
    @RequestMapping(value = "/student/import", method = RequestMethod.PUT)
    public R confirmBatchSocialStudentInfo(String uuid, HttpServletRequest request){
        return socialStudentService.confirmBatchSocialStudentInfo(uuid, AccessTokenUtil.getUserId(request)) ? R.success() : R.fail(ResponseEnum.CACHE_NOT_EXIST);
    }

    /**
     * 导出导入失败学员信息
     * @param uuid 导入uuid
     * @param response http响应对象
     * @return null
     */
    @RequestMapping(value = "/student/import", method = RequestMethod.GET)
    public R exportImportFailedSocialStudentInfo(String uuid, HttpServletResponse response){
        try {
            socialStudentService.exportImportFailedSocialStudentInfo(uuid, response);
        } catch (Exception e) {
            return R.fail(0, e.getMessage());
        }
        return R.success();
    }

    /**
     * 根据检索信息导出社会化学员列表
     * @param param 检索信息
     * @param response http 响应对象
     * @return 导出结果
     */
    @RequestMapping(value = "/student/export", method = RequestMethod.GET)
    public R exportSocialStudentInfo(SocialStudentPageParam param, HttpServletResponse response){
        return socialStudentService.exportSocialStudentInfo(param, response) ? null : R.fail(ResponseEnum.PARAM_IS_INVAlID);
    }

    /**
     * 根据当前年份获取项目自动编号后缀
     * @return 项目自动编号后缀
     */
    @RequestMapping(value = "/autoNum/project", method = RequestMethod.GET)
    public R generateProjectNumByCurrentYear(){
        // 获取所有项目数据
        List<SocialProject> socialProjectList = socialProjectService.getSocialProjectListWithoutLogicDelete();
        // 获取当前年份
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        int year = calendar.get(Calendar.YEAR);
        // 统计当前年份的项目数
        long count = socialProjectList.stream().filter(socialProject -> {
            Date startTime = socialProject.getStartTime();
            Calendar calendar1 = Calendar.getInstance();
            calendar1.setTime(startTime);
            int y = calendar1.get(Calendar.YEAR);
            return y == year;
        }).count();
        return R.success(String.format("%03d", count + 1));
    }

    /**
     * 根据项目ID获取班级自动编号后缀
     * @param projectId 社会化项目ID
     * @return 响应结果
     */
    @RequestMapping(value = "/autoNum/clazz", method = RequestMethod.GET)
    public R generateClazzNumByProjectId(@RequestParam Long projectId){
        List<SocialClazz> socialClazzList = socialClazzService.getSocialClazzListWithoutLogicDelete();
        long count = socialClazzList.stream().filter(socialClazz -> socialClazz.getProjectId().equals(projectId)).count();
        return R.success(String.format("%02d", count + 1));
    }

    /**
     * 获取中文拼音
     * @param string 中文字符串
     * @return 拼音
     */
    @RequestMapping(value = "/pinyin", method = RequestMethod.GET)
    public R getPinyin(@RequestParam String string){

        return R.success(PinyinUtil.getFirstLetter(string, "").toUpperCase());
    }

}
